﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel.Core;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using com.IronOne.BoardPACWinApp.Sync;
using com.IronOne.BoardPACWinApp.View.Page;
using com.IronOne.BoardPACWinAppBO.Agenda;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppBO.Sync;
using com.IronOne.BoardPACWinAppService.Agenda;
using com.IronOne.BoardPACWinAppUtil.Enums;
using com.IronOne.BoardPACWinAppUtil.Util;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;

namespace com.IronOne.BoardPACWinApp.ViewModel
{
    public class TreeViewPageViewModel : ViewModelBase
    {
        public const string SelectedAgendaItemName = "SelectedAgendaItem";

        public static int MeetingId;
        private List<AgendaItem> _fullAgendaItems;
        
        private int _searchFlyoutWidth;
        private AgendaItem _selectedAgendaItem;
        private AgendaItem _globalSelectedAgendaItem;
        private readonly IAgendaService _agendService;
        private const string Path2 = "ms-appx:///Assets/Images/AgendaPage/";
        private const string SelectedColor = "#9cddef";

        public TreeViewPageViewModel(int meetingId, AgendaItem globalSelectedAgendaItem)
        {
            
            try
            {
                _globalSelectedAgendaItem = globalSelectedAgendaItem;
                Messenger.Default.Register<NotificationMessage<MessageDataModel>>(this, HandleMessages);
                SyncManager.GetPaperDownloadOperationStatusEvt += (HandlePaperDownloadOperationStatus);
                AgendaPage.AgendaItemForceDownloadEvt += AgendaPage_AgendaItemForceDownloadEvt;

                MeetingId = meetingId;
                Messenger.Default.Register<ObservableCollection<AgendaItem>>(this, "ChildAgendaList", BuildTree);
                Messenger.Default.Register<int>(this, "IDPropertyNameChanged", SetId);
                _agendService = new AgendaService();
                GetAgendaItems(meetingId);

                _searchFlyoutWidth = (int) (Window.Current.Bounds.Width*0.2);
                if (_searchFlyoutWidth < Utility.GetFlyoutDefaultWidth())
                    _searchFlyoutWidth = Utility.GetFlyoutDefaultWidth();

                AgendaItem.CloseAgendaPresenterEvt += AgendaItem_CloseAgendaPresenterEvt;

                AgendaItem.AgendaItemClickBgEvtHandler -= OnAgendaItemClickBgEvt;
                AgendaItem.AgendaItemClickBgEvtHandler = null;
                AgendaItem.AgendaItemClickBgEvtHandler += OnAgendaItemClickBgEvt;

                AgendaPage.AgendaItemClickPaperStatusSideIconEvtHandler -= OnAgendaItemClick_PaperStatusSideIconEvt;
                AgendaPage.AgendaItemClickPaperStatusSideIconEvtHandler = null;
                AgendaPage.AgendaItemClickPaperStatusSideIconEvtHandler += OnAgendaItemClick_PaperStatusSideIconEvt;
            }
            catch (Exception)
            {
            }
        }

        public int AgendaItemId { get; set; }

        /// <summary>
        ///     Sets and gets the MyProperty property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public int SearchFlyoutWidth
        {
            get { return _searchFlyoutWidth; }

            set
            {
                if (_searchFlyoutWidth == value)
                {
                    return;
                }

                _searchFlyoutWidth = value;
                RaisePropertyChanged("SearchFlyoutWidth");
            }
        }

        /// <summary>
        ///     Sets and gets the SelectedAgendaItem property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public AgendaItem SelectedAgendaItem
        {
            get { return _selectedAgendaItem; }

            set
            {
                if (_selectedAgendaItem == value)
                {
                    return;
                }

                _selectedAgendaItem = value;
                RaisePropertyChanged(SelectedAgendaItemName);
            }
        }

        public List<AgendaItem> FullAgendaItems
        {
            get { return _fullAgendaItems; }
            set
            {
                _fullAgendaItems = value;
                BuildTree();
            }
        }

        protected async void HandleMessages(NotificationMessage<MessageDataModel> mdm)
        {
            if (mdm.Notification.Equals(MessageCodes.SYNC_UPDATED_DATA))
            {
                try
                {
                    var sudm = (SyncUpdatedDataModel) mdm.Content.MessageData;

                    if ((sudm.AgendaItemIds != null && sudm.AgendaItemIds.Count > 0) ||
                        (sudm.HeadingIds != null && sudm.HeadingIds.Count > 0) ||
                        sudm.IsUpdatedOrDeletedAgendaItems ||
                        sudm.IsUpdatedOrDeletedHeadingItems ||
                        (sudm.Comments != null && sudm.Comments.Count > 0))
                    {
                        await
                            CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                async () => { await GetAgendaItems(MeetingId); });
                    }
                }
                catch (Exception)
                {
                }
            }
        }

        public void SetId(int id)
        {
            AgendaItemId = id;
        }

        private async void AgendaItem_CloseAgendaPresenterEvt(AgendaItem agendaItem)
            //Change Binding in Update Paper Present flyout
        {
            try
            {
                var meetingId = agendaItem.MeetingId;
                var paperId = agendaItem.Id;

                var rslt = await _agendService.UpdatePaperPresentStatus(meetingId, paperId);

                if (rslt)
                {
                    agendaItem.ItemStatus = "Closed";
                    agendaItem.PresenterCloseBtnVisibility = Visibility.Collapsed;
                }
            }
            catch (Exception)
            {
            }
        }

        private void OnAgendaItemClickBgEvt(object sender, EventArgs e)
        {
            try
            {
                foreach (var aitem in FullAgendaItems)
                {
                    aitem.AgendaItemDefaultBg = "#FFF2FBFF";

                    if (aitem.Id == ((AgendaItem) sender).Id)
                    {
                        aitem.AgendaItemDefaultBg = SelectedColor;
                        _globalSelectedAgendaItem = aitem;
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        /*private void PaperStatusSideIconChangeEvt(AgendaItem agendaItem, bool isSuccess)
        {
            AgendaItem item = null;
            try
            {
                item = FullAgendaItems.FirstOrDefault(x => x.ID == agendaItem.ID && x.HeadorPaper == 1);
                if (isSuccess)
                    item.MeetingStatusSideIconVisibility = Visibility.Collapsed;
                else
                    item.MeetingStatusSideIconVisibility = Visibility.Visible;
            }
            catch (Exception)
            {
                item.MeetingStatusSideIconVisibility = Visibility.Collapsed;
            }
        }*/

        private void BuildTree()
        {
            var tree = BuildChildrenTree(_fullAgendaItems.Where(a => a.PreviousId == null).ToList());
            TreeItems = tree;
        }

        //Method will call for agenda item heading single click
        private void BuildTree(ObservableCollection<AgendaItem> list)
        {
            if (list.Count > 0)
            {
                BuildTree();
            }
        }

        private ObservableCollection<AgendaItem> BuildChildrenTree(List<AgendaItem> agendaItems)
        {
            var tree = new ObservableCollection<AgendaItem>();

            try
            {
                foreach (var item in agendaItems)
                {
                    item.Children =
                        BuildChildrenTree(
                            FullAgendaItems.Where(a => a.PreviousId == item.Id && item.HeadorPaper == 0).ToList());

                    #region Change bg color of the currently seleted item

                    if (_globalSelectedAgendaItem != null && _globalSelectedAgendaItem.Id == item.Id)
                    {
                        item.AgendaItemDefaultBg = SelectedColor;
                    }

                    #endregion

                    tree.Add(item);
                }
            }
            catch (Exception)
            {
            }
            return tree;
        }

        private async Task GetAgendaItems(int meetingId)
        {
            try
            {
                var items = await _agendService.GetAgenda(meetingId);
                FullAgendaItems = items;
            }
            catch (Exception)
            {
            }
        }

        public void HandlePaperDownloadOperationStatus(PaperDownloadStatuses status, int paperId)
        {
            try
            {
                var item = FullAgendaItems.FirstOrDefault(x => x.Id == paperId && x.HeadorPaper == 1);
                if (item == null) return;
                switch ((int) status)
                {
                    case (int) PaperDownloadStatuses.Downloding:
                        item.DownloadStatusIconPath = Path2 + "Agenda_DownloadStart.png";
                        item.DownloadStatus = (int) PaperDownloadStatuses.Downloding;
                        break;
                    case (int) PaperDownloadStatuses.NotDownloded:
                        item.DownloadStatusIconPath = Path2 + "Agenda_DownloadPause.png";
                        item.DownloadStatus = (int) PaperDownloadStatuses.NotDownloded;
                        break;
                    case (int) PaperDownloadStatuses.DownloadError:
                        item.DownloadStatusIconPath = Path2 + "Agenda_DownloadPause.png";
                        item.DownloadStatus = (int) PaperDownloadStatuses.DownloadError;
                        break;
                    case (int) PaperDownloadStatuses.Downloded:
                        item.DownloadStatusIconPath = "";
                        item.DownloadStatus = (int) PaperDownloadStatuses.Downloded;
                        break;
                    default:
                        item.DownloadStatusIconPath = "";
                        break;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void AgendaPage_AgendaItemForceDownloadEvt(PaperDownloadStatuses stat, int agendaItemId)
        {
            try
            {
                HandlePaperDownloadOperationStatus(stat, agendaItemId);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void OnAgendaItemClick_PaperStatusSideIconEvt(object sender, EventArgs e)
        {
            try
            {
                var content = (Tuple<AgendaItem, bool>) sender;
                var agendaItemId = content.Item1.Id;

                var items =
                    FullAgendaItems.FirstOrDefault(a => a.Id == agendaItemId && content.Item1.HeadorPaper == 1);
                items.MeetingStatusSideIconBgColor = "Transparent";
                items.MeetingStatusSideIconVisibility = Visibility.Collapsed;
            }
            catch (Exception)
            {
                throw;
            }
        }

        #region TreeItems

        private ObservableCollection<AgendaItem> _treeItems;
        public const string TreeItemsPropertyName = "TreeItems";

        public ObservableCollection<AgendaItem> TreeItems
        {
            get { return _treeItems; }
            set
            {
                _treeItems = value;
                RaisePropertyChanged(TreeItemsPropertyName);
            }
        }

        #endregion

        #region Agenda Search

        public const string SearchedItemsPropertyName = "SearchedItems";

        private ObservableCollection<AgendaItem> _searchedItems;

        public ObservableCollection<AgendaItem> SearchedItems
        {
            get { return _searchedItems; }

            set
            {
                _searchedItems = value;
                RaisePropertyChanged(SearchedItemsPropertyName);
            }
        }

        public const string QueryTextPropertyName = "QueryText";

        private string _queryText;

        public string QueryText
        {
            get { return _queryText; }

            set
            {
                _queryText = value;

                RaisePropertyChanged(QueryTextPropertyName);
                GetSearchedItems(_queryText);
            }
        }

        private readonly SolidColorBrush _agendaItemNormalColor = new SolidColorBrush(Color.FromArgb(255, 23, 133, 186));
        private readonly SolidColorBrush _agendaHeadingItemNormalColor = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
        private readonly SolidColorBrush _agendaItemHilightColor = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));

        /// <summary>
        ///     The <see cref="SearchListSelectedItem" /> property's name.
        /// </summary>
        public const string SearchListSelectedItemPropertyName = "SearchListSelectedItem";

        private AgendaItem _searchListSelectedItem;

        /// <summary>
        ///     Sets and gets the SearchListSelectedItem property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public AgendaItem SearchListSelectedItem
        {
            get { return _searchListSelectedItem; }

            set
            {
                try
                {
                    var oldValue = _searchListSelectedItem;
                    _searchListSelectedItem = value;

                    if (_searchListSelectedItem != null)
                    {
                        //Clear highlighted items when specific item selected
                        foreach (var matchedItem in _matchedList)
                        {
                            matchedItem.AgendaItemNameColor = matchedItem.HeadorPaper == 0
                                ? _agendaHeadingItemNormalColor
                                : _agendaItemNormalColor;
                        }

                        _searchListSelectedItem.IsFocused = false;
                        var item = _searchListSelectedItem.HeadorPaper == 0
                            ? _fullAgendaItems.FirstOrDefault(a => a.Id.Equals(_searchListSelectedItem.Id) && a.HeadorPaper == 0)
                            : _fullAgendaItems.FirstOrDefault(a => a.Id.Equals(_searchListSelectedItem.Id) && a.HeadorPaper == 1);

                        item.IsFocused = true;
                        item.AgendaItemNameColor = _agendaItemHilightColor;
                    }
                    else
                    {
                        oldValue.AgendaItemNameColor = oldValue.HeadorPaper == 0
                            ? _agendaHeadingItemNormalColor
                            : _agendaItemNormalColor;
                        BuildTree();
                        GetSearchedItems(_queryText);
                    }
                    RaisePropertyChanged(SearchListSelectedItemPropertyName);
                }
                catch (Exception)
                {
                }
            }
        }


        //Search command for agenda list searching
        private RelayCommand _searchCommand;

        public RelayCommand SearchCommand
        {
            get
            {
                return _searchCommand
                       ?? (_searchCommand = new RelayCommand(
                           () => { GetSearchedItems(QueryText); }));
            }
        }


        private List<AgendaItem> _matchedList;

        private void GetSearchedItems(string queryText)
        {
            try
            {
                _matchedList = new List<AgendaItem>();

                foreach (var item in _fullAgendaItems)
                {
                    if (string.IsNullOrEmpty(queryText))
                    {
                        item.AgendaItemNameColor = item.HeadorPaper == 0
                            ? _agendaHeadingItemNormalColor
                            : _agendaItemNormalColor;
                    }
                    else if (item.Name.ToLower().Contains(queryText.ToLower()))
                    {
                        item.AgendaItemNameColor = _agendaItemHilightColor;
                        _matchedList.Add(item);
                    }
                    else
                    {
                        item.AgendaItemNameColor = item.HeadorPaper == 0
                            ? _agendaHeadingItemNormalColor
                            : _agendaItemNormalColor;
                    }
                }

                SearchedItems = new ObservableCollection<AgendaItem>(_matchedList);
            }
            catch (Exception)
            {
            }
        }


        //Search close button command
        private RelayCommand _searchCloseCommand;

        public RelayCommand SearchCloseCommand
        {
            get
            {
                return _searchCloseCommand
                       ?? (_searchCloseCommand = new RelayCommand(
                           () =>
                           {
                               if (_matchedList != null)
                               {
                                   foreach (var matchedItem in _matchedList)
                                   {
                                       matchedItem.AgendaItemNameColor = matchedItem.HeadorPaper == 0
                                           ? _agendaHeadingItemNormalColor
                                           : _agendaItemNormalColor;
                                   }
                               }
                           }));
            }
        }

        #endregion

        #region Testing

        /// <summary>
        ///     The <see cref="IsExpanded" /> property's name.
        /// </summary>
        public const string IsExpandedPropertyName = "IsExpanded";

        private bool _isExpanded = true;

        /// <summary>
        ///     Sets and gets the IsExpanded property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public bool IsExpanded
        {
            get { return _isExpanded; }

            set
            {
                if (_isExpanded == value)
                {
                    return;
                }

                _isExpanded = value;
                RaisePropertyChanged(IsExpandedPropertyName);
            }
        }

        #endregion
    }
}